package com.example.workflow.service.impl;

import com.example.workflow.dto.ApprovalInfo;
import com.example.workflow.dto.DispatcherOrder;
import com.example.workflow.dto.FormDto;
import com.example.workflow.exception.ServiceException;
import com.example.workflow.flow.BizFlowTypeEnum;
import com.example.workflow.mapper.FormMapper;
import com.example.workflow.mapper.UserInfoMapper;
import com.example.workflow.pojo.Form;
import com.example.workflow.pojo.LoginUser;
import com.example.workflow.service.FormService;
import com.example.workflow.service.UserInfoService;
import com.example.workflow.util.FlowUtil;
import com.example.workflow.vo.FormVo;
import com.example.workflow.vo.RemindVo;
import com.example.workflow.vo.UserInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


@Service
@Slf4j
public class FormServiceImpl implements FormService {

//    部门和对应处理表单类型之间的映射表
    public static Map<String,List<String>> type_map = Map.of(
            "光缆维护部",List.of("光缆故障","新增光缆布放","光缆定期巡检"),
        "基站运维部",List.of("基站故障","基站扩容","基站设备保养","网络架构调整"),
        "电力保障部",List.of("电力供应故障","电力设施升级","电力设施维护","重大活动电力保障"),
        "数据运维部",List.of("服务器故障","服务器采购","服务器维护","数据中心能效优化"),
        "应急抢修部",List.of("灾害性突发故障")
    );

    @Autowired
    private FormMapper formMapper;

    @Autowired
    private UserInfoService userInfoService;

    /**
     * 新建工单
     *
     * @param formDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(FormDto formDto) {
        log.info("创建工单");
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        if(formDto.getId()==null)
        {
            Form form = new Form();
            form.setTitle(formDto.getTitle());
            form.setType(formDto.getType());
            form.setSubtype(formDto.getSubtype());
            form.setContent(formDto.getContent());
            form.setStatus("draft");
            form.setCreateUser(loginUser.getUserInfo().getId());
            formMapper.create(form);
        } else {
            formMapper.updateDraft(formDto);
        }
    }

    /**
     * 提交工单
     *
     * @param formDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submit(FormDto formDto) {
        log.info("提交工单");
        long expect_time = 86400000 * 3L;
        try
        {
            Long orderId = null;
            if (formDto.getId() == null) {
                Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                LoginUser loginUser = (LoginUser) authentication.getPrincipal();

                Form form = new Form();
                form.setTitle(formDto.getTitle());
                form.setType(formDto.getType());
                form.setSubtype(formDto.getSubtype());
                form.setContent(formDto.getContent());
                form.setStatus("pending_l1");
                form.setCreateUser(loginUser.getUserInfo().getId());
                // 更新创建时间，得到预期完成时间
                Date date = new Date();
                form.setCreateTime(date);
                form.setExpectFinishTime(new Date(date.getTime() + expect_time + 20));
                formMapper.create(form);
                log.info("新增orderId  "+form.getId());
                orderId = form.getId();

            } else {
                String status = formMapper.details(formDto.getId()).getStatus();
                if(!status.equals("draft")){
                    throw new ServiceException("当前工单已经提交，操作失败");
                }

                Date date = new Date();
                formDto.setCreateTime(date);
                formDto.setExpectFinishTime(new Date(date.getTime() + expect_time + 20));
                formDto.setStatus("pending_l1");
                formMapper.submit(formDto);
                orderId=formDto.getId();

            }
            log.info("新增工单{}", orderId);
            String type = formDto.getSubtype();
            List<UserInfoVo> userList = switch (type) {
                case "光缆故障", "新增光缆布放", "光缆定期巡检" -> userInfoService.userList(null,null, "光缆维护部", null);
                case "基站故障", "基站扩容", "基站设备保养", "网络架构调整" ->
                        userInfoService.userList(null,null, "基站运维部", null);
                case "电力供应保障", "电力设施升级", "电力设施维护", "重大活动电力保障" ->
                        userInfoService.userList(null,null, "电力保障部", null);
                case "服务器故障", "服务器采购", "服务器维护", "数据中心能效优化" ->
                        userInfoService.userList(null,null, "数据运维部", null);
                default -> userInfoService.userList(null,null, "应急抢修部", null);
            };

            log.info("userList:{}", userList);

            Set<String> cityUsers = userList.stream().filter(x -> Objects.equals(x.getRole(), "CITY"))
                    .map(item -> item.getId().toString()).collect(Collectors.toSet());
            Set<String> provinceUsers = userList.stream().filter(x -> Objects.equals(x.getRole(), "PROVINCE"))
                    .map(item -> item.getId().toString()).collect(Collectors.toSet());
            Set<String> operatorUsers = userList.stream().filter(x -> Objects.equals(x.getRole(), "OPERATOR"))
                    .map(item -> item.getId().toString()).collect(Collectors.toSet());
            Map<String,Object> params = new HashMap<>();
            params.put("cityUsers", cityUsers);
            params.put("provinceUsers", provinceUsers);
            params.put("operatorUsers", operatorUsers);
            params.put("pass", true);
            params.put("needDispatch",false);
            params.put("duration","PT1M"); // 设置超时时间1为一分钟

            FlowUtil.startProcess(BizFlowTypeEnum.ORDER_APPROVE.getKey(),orderId,params);

        } catch (Exception e) {
            throw new RuntimeException(e);
//            throw new ServiceException("提交工单操作失败");
        }
    }

    /**
     *
     * 查询个人处理的工单
     * @return
     */
    @Override
    public List<FormVo> list(Long id, String type, String status) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        // TODO  区分一级/二级审批

        String role = loginUser.getUserInfo().getRole();
        log.info("role{}", role);
        ArrayList<FormVo> forms = new ArrayList<>();
        switch (role) {
            case "CITY" -> {
                List<String> types = type_map.get(loginUser.getUserInfo().getDepartment());
                return formMapper.list(types, "pending_l1",id,type);
            }
            case "PROVINCE" -> {
                List<String> types = type_map.get(loginUser.getUserInfo().getDepartment());
                return formMapper.list(types, "pending_l2",id,type);

            }
            case "OPERATOR" -> {
                // TODO
                List<String> types = type_map.get(loginUser.getUserInfo().getDepartment());
//                // // System.out.println("types "+types);

//                log.info("type,{}",type);
                  System.out.println(formMapper.operatorList(types,loginUser.getUserInfo().getDepartment(),id,type,status));

                return formMapper.operatorList(types,loginUser.getUserInfo().getDepartment(),id,type,status);

            }
            case "USER" -> {
                // TODO 查
                return formMapper.draftBox(loginUser.getUserInfo().getId(),id,type,status);
            }
            case "ADMIN" -> {
                return formMapper.adminList(id,type,status);
            }
        }
//        // // System.out.println("forms "+forms);
        return forms;
    }

    /**
     * 查看个人操作的单子
     *
     * @return
     */
    @Override
    public List<FormVo> process() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        // TODO  区分一级/二级审批

        List<String> types = type_map.get(loginUser.getUserInfo().getDepartment());
        return formMapper.list(types,"processing",null,null);
    }

    /**
     * 审批接口
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object approval(ApprovalInfo approvalInfo) {
        // TODO 区分一级通过/二级通过
        if(approvalInfo.getOrderId()==null) {
            throw new ServiceException("工单ID不能为空");
        }
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        String stand = loginUser.getUserInfo().getRole();
        approvalInfo.setUserId(loginUser.getUserInfo().getId());
        int affectedRows=-1;

        log.info("审批  {}",approvalInfo);

        log.info("审批  ,{}",formMapper.details(approvalInfo.getOrderId()));
        String status = formMapper.details(approvalInfo.getOrderId()).getStatus();


        if((!status.equals("pending_l1")&&stand.equals("CITY"))||(!status.equals("pending_l2")&&stand.equals("PROVINCE"))) {
            throw new ServiceException(HttpStatus.UNAUTHORIZED.value(),"当前工单不予审批");
        }
        if(approvalInfo.getAttitude().equals("通过"))
        {
            FlowUtil.claimAndCompleteTask(BizFlowTypeEnum.ORDER_APPROVE.getKey(),approvalInfo.getOrderId().toString(),approvalInfo.getUserId().toString(),null);

            if (stand.equals("CITY")) {
                 affectedRows = formMapper.approval(approvalInfo);
            } else if (stand.equals("PROVINCE")) {
                affectedRows = formMapper.approvalSecond(approvalInfo);
                formMapper.insertLog(approvalInfo.getOrderId());
            }
        } else if(approvalInfo.getAttitude().equals("驳回")) {
//            TODO 更改流程变量pass=false
            Map<String,Object> params = new HashMap<>();
            params.put("pass",true);
            FlowUtil.claimAndCompleteTask(BizFlowTypeEnum.ORDER_APPROVE.getKey(),approvalInfo.getOrderId().toString(),approvalInfo.getUserId().toString(),params);
            // 操作时间
            approvalInfo.setFinishTime(new Date());
//            FlowUtil.destroyProcess(BizFlowTypeEnum.ORDER_APPROVE.getKey(), approvalInfo.getOrderId().toString(),approvalInfo.getAdvice(),approvalInfo.getUserId().toString());
            if (stand.equals("CITY")) {
                affectedRows = formMapper.reject(approvalInfo);
            } else if (stand.equals("PROVINCE")) {
                affectedRows = formMapper.rejectSecond(approvalInfo);
            }
        }
        if(affectedRows==0) {
            throw new ServiceException("工单已经被其他工作人员修改");
        }
        return null;
    }

    /**
     * 审批驳回
     *
     * @param orderId 工单ID
     */
    @Override
    public void reject(Long orderId) {
//        formMapper.reject(orderId);

    }

    /**
     * 分派工单
     *
     * @param dispatcherOrder 分派信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void dispatcher(DispatcherOrder dispatcherOrder) {
        if(dispatcherOrder.getOrderId()==null) {
            throw new ServiceException("工单ID不能为空");
        }
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        String status = formMapper.details(dispatcherOrder.getOrderId()).getStatus();

        if (dispatcherOrder.getNeedDispatch().equals("需要协助")) {
            // 需要帮助
//            TODO 设置流程变量needDispatch==true 设置需要协助的部门人员
            Map<String,Object> params = new HashMap<>();
            // System.out.println("需要协助  ");
            // System.out.println("dispatcherOrder"+dispatcherOrder);
            if(dispatcherOrder.getDept()==null) {
                throw new ServiceException("协助部门不能为空");
            }
            List<UserInfoVo> helpUserList = userInfoService.userList(null,null,dispatcherOrder.getDept(),"OPERATOR");
            Set<String> helpUsers = helpUserList.stream().map(item -> item.getId().toString()).collect(Collectors.toSet());
            // System.out.println("helpUsers "+helpUsers);
            params.put("needDispatch",true);
            params.put("helpUsers", helpUsers);
            FlowUtil.claimAndCompleteTask(BizFlowTypeEnum.ORDER_APPROVE.getKey(),dispatcherOrder.getOrderId().toString(),loginUser.getUserInfo().getId().toString(),params);

            formMapper.dispatcher(dispatcherOrder);

        } else {
            // 不需要帮助
//            TODO 设置流程变量needDispatch==false
            Map<String,Object> params = new HashMap<>();
            params.put("needDispatch",false);

            formMapper.operate(dispatcherOrder);
            FlowUtil.claimAndCompleteTask(BizFlowTypeEnum.ORDER_APPROVE.getKey(),dispatcherOrder.getOrderId().toString(),loginUser.getUserInfo().getId().toString(),params);
        }
    }

    /**
     * 工单详情
     *
     * @param id
     * @return
     */
    @Override
    public Form details(Long id) {
        if(id==null) {
            throw new ServiceException("工单ID不能为空");
        }
        Form form = formMapper.details(id);
        if (form == null) {
            throw new ServiceException("当前工单不存在");
        }
        if(form.getAssistUnit()!=null) {
            form.setIsDistribute(true);
        }
        return form;
    }

    /**
     * 完成工单
     *
     * @param orderId 工单ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void complete(Long orderId,String log) {
        if(orderId==null) {
            throw new ServiceException("工单ID不能为空");
        }
        Form form = formMapper.details(orderId);
        // System.out.println("complete   "+form);
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        FlowUtil.claimAndCompleteTask(BizFlowTypeEnum.ORDER_APPROVE.getKey(),orderId.toString(),loginUser.getUserInfo().getId().toString(),null);

        if(form.getStatus().equals("dispatched")) {
            if (form.getSumComplete() == 2) {
                throw new ServiceException("已经操作完成，无需操作");
            } else if (form.getSumComplete() == 1) {
                // 需要完成操作并且转移到状态3
                // 判断是主要部门or协同部门
                if (form.getFlag() == 1 && loginUser.getUserInfo().getDepartment().equals(form.getAssistUnit())) {
                    // System.out.println("主单位已经完成，协助单位进入");
                    formMapper.complete(orderId, new Date());
                    formMapper.completeSecond(orderId, loginUser.getUserInfo().getId(), log, new Date());
                } else if (form.getFlag() == 2) {
                    // System.out.println("协助单位完成，主要单位进入");
                    formMapper.complete(orderId, new Date());
                    formMapper.completeFirst(orderId, loginUser.getUserInfo().getId(), log, new Date());
                } else {
                    throw new ServiceException("操作失败");
                }
            } else if (form.getSumComplete() == 0) {
                if (loginUser.getUserInfo().getDepartment().equals(form.getAssistUnit())) {
                    // System.out.println("住单位进入");
                    formMapper.updateSecond(orderId, loginUser.getUserInfo().getId(), log, new Date());
                } else {
                    // System.out.println("协助单位进入");
                    formMapper.updateFirst(orderId, loginUser.getUserInfo().getId(), log, new Date());
                }
            } else {
                throw new ServiceException("操作失败");
            }
//        } else if(form.getStatus().equals("processing")) {
        } else if(form.getStatus().equals("operating")) {

            formMapper.complete(orderId,new Date());
            formMapper.completeFirst(orderId,loginUser.getUserInfo().getId(),log,new Date());
        }
//        if(form.getStatus().equals("processing")) {formMapper.complete(orderId);}
//        else if(form.getStatus().equals("dispatched")) {formMapper.back(orderId);}

    }

    /**
     * 超时预警信息
     *
     * @return
     */
    @Override
    public long remind() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        long totalSum = 0;
        String role = loginUser.getUserInfo().getRole();
        switch (role) {
            case "CITY" -> {
                List<String> types = type_map.get(loginUser.getUserInfo().getDepartment());
                long sum = formMapper.timeoutList(types, "pending_l1");
                totalSum = totalSum + sum;
            }
            case "PROVINCE" -> {
                List<String> types = type_map.get(loginUser.getUserInfo().getDepartment());

                long sum = formMapper.timeoutList(types, "pending_l2");
                totalSum = totalSum + sum;

            }
            case "OPERATOR" -> {
                // TODO
                List<String> types = type_map.get(loginUser.getUserInfo().getDepartment());
                long sum = formMapper.timeoutOperatorList(types,loginUser.getUserInfo().getDepartment());
                totalSum = totalSum + sum;
            }
        }
//        // // System.out.println("forms "+forms);
        return totalSum;
    }

    /**
     * 删除草稿工单
     *
     * @param id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        if(id==null) {
            throw new ServiceException("工单ID不能为空");
        }
        formMapper.delete(id);
    }

}
